#ifndef Marks_First
#define Marks_First
#ifdef __GNUG__
#pragma interface
#endif

#include "Object.h"

class SeqCollection;

//---- constants passed to DoObserve to the dependents of a mark

enum eMarkChanges  {
	eMarkNone = 0,
	eMarkDeleted,      // mark deleted
	eMarkLength,       // text in mark range changed
	eMarkPos           // position of the mark changed
};

//---- states of a mark

enum eMarkState {
	eStateNone = 0,
	eStateDeleted = 1,
	eStateChanged = 2,
};

enum eMarkFlags {
	eMarkInclStart  =   BIT(eObjLast+1),
	eMarkFixedSize  =   BIT(eObjLast+2),
	eMarkLocked     =   BIT(eObjLast+3),   // mark won't move
	eMarkDefault    =   eMarkInclStart,
	eMarkLast       =   eObjLast + 3
};

//---- Mark --------------------------------------------------------------------

class Mark: public Object {
public:
	int pos, len, state;

public:
	MetaDef(Mark);
	Mark(int p= 0, int l= 0, eMarkState s= eStateNone, eMarkFlags f= eMarkDefault);
	Mark(Mark *m);
	void ChangeMark (int p, int l, int s= 0)
		{ pos = p; len = l; state = s; }
	bool HasChanged(int start, int len);
	int Len()
		{ return len; }
	int Pos()
		{ return pos; }
	int End()
		{ return pos+len; }
	eMarkState State()
		{ return (eMarkState)state; }
	void Lock()
		{ SetFlag(eMarkLocked); }
	void Unlock()
		{ ResetFlag(eMarkLocked); }
	int Compare (Object* op);

	//---- editing
	void Cut(int at, int len);
	void Paste(int at, int len);
	void Change(int at, int len);

	//---- generic
	Object *deepclone();
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);
};

//---- MarkList ----------------------------------------------------------------

class MarkList: public Object {
	SeqCollection *marks;
	bool doRemove;
public:
	MetaDef(MarkList);
	MarkList(bool doRemove = FALSE, SeqCollection *rep= 0);
			// remove the deleted marks from the marklist?,
			// representation of marklist
	~MarkList();

	void Add(Mark *m);
	Mark *Remove(Mark *m);
	Iterator *MakeIterator(void *placement= 0);
	int Size();
	void FreeAll();
	void Empty();
	Mark *At(int i);

	//---- editing
	void Replace(int from, int to, int n);
	void RangeChanged(int at, int len); // mark marks in the given range as changed

	//---- object I/O
	OStream& PrintOn(OStream&);
	IStream& ReadFrom(IStream&);
};

#endif
